package com.hzw.saas.web.app.schedule.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hzw.saas.api.schedule.IUserScheduleGroupService;
import com.hzw.saas.api.schedule.IUserScheduleMeetingService;
import com.hzw.saas.api.schedule.IUserScheduleService;
import com.hzw.saas.api.schedule.IUserScheduleTagService;
import com.hzw.saas.api.schedule.bo.*;
import com.hzw.saas.api.schedule.query.*;
import com.hzw.saas.common.config.annotation.SysLog;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.config.util.PageParam;
import com.hzw.saas.common.security.utils.SecurityUtils;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.service.schedule.model.UserScheduleGroup;
import com.hzw.saas.service.schedule.model.UserScheduleTag;
import com.hzw.saas.web.app.schedule.param.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiOperationSort;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @author hankun
 */
@Slf4j
@RestController
@Validated
@Api(tags = "我的日程")
public class UserScheduleController {

    @Resource
    private IUserScheduleService userScheduleService;
    @Resource
    private IUserScheduleGroupService userScheduleGroupService;
    @Resource
    private IUserScheduleTagService userScheduleTagService;
    @Resource
    private IUserScheduleMeetingService userScheduleMeetingService;

    @ApiOperationSort(1)
    @PostMapping("schedule")
    @SysLog(operation = "创建日程任务")
    @ApiOperation(value = "创建日程任务")
    public ResponseEntity<Boolean> addSchedule(@RequestBody UserScheduleAddParam userScheduleAddParam) {
        UserScheduleAddQuery scheduleAddQuery = MapperUtil.nf().map(userScheduleAddParam, UserScheduleAddQuery.class);
        scheduleAddQuery.setUserId(SecurityUtils.getUserId());
        Boolean result = userScheduleService.addSchedule(scheduleAddQuery);
        return ResponseEntity.ok(result);
    }

    @ApiOperationSort(2)
    @PutMapping("schedule")
    @SysLog(operation = "更新日程任务")
    @ApiOperation(value = "更新日程任务",
            notes = "1.包括移除 -> 转移到垃圾箱中\n2.仅支持个人日程任务, 会议任务除外\n3.不支持点击完成任务")
    public ResponseEntity<Boolean> updateSchedule(@RequestBody UserScheduleUpdateParam userScheduleUpdateParam) {
        UserScheduleUpdateQuery scheduleUpdateQuery = MapperUtil.nf().map(userScheduleUpdateParam, UserScheduleUpdateQuery.class);
        scheduleUpdateQuery.setUserId(SecurityUtils.getUserId());
        Boolean result = userScheduleService.updateSchedule(scheduleUpdateQuery);
        return ResponseEntity.ok(result);
    }

    @ApiOperationSort(3)
    @GetMapping("schedule")
    @SysLog(operation = "获取日程任务")
    @ApiOperation(value = "获取日程任务")
    public ResponseEntity<IPage<UserScheduleBo>> getSchedule(UserScheduleSearchParam userScheduleSearchParam, PageParam pageParam) {
        Page<UserScheduleBo> page = pageParam.convert();
        UserScheduleQuery userScheduleQuery = MapperUtil.nf().map(userScheduleSearchParam, UserScheduleQuery.class);
        userScheduleQuery.setUserId(SecurityUtils.getUserId());
        IPage<UserScheduleBo> iPage = userScheduleService.getSchedule(userScheduleQuery, page);
        return ResponseEntity.ok(iPage);
    }

    @ApiOperationSort(3)
    @GetMapping("schedule/view")
    @SysLog(operation = "获取日程任务 日历视图")
    @ApiOperation(value = "获取日程任务 日历视图")
    public ResponseEntity<List<UserScheduleViewBo>> getScheduleView(UserScheduleViewParam viewParam) {
        AssertUtil.assertThrow("参数不合法", viewParam.getEndDate().isBefore(viewParam.getStartDate()));
        UserScheduleViewQuery userScheduleViewQuery = new UserScheduleViewQuery()
                .setUserId(SecurityUtils.getUserId())
                .setStartDateTime(viewParam.getStartDate().atStartOfDay())
                .setEndDateTime(viewParam.getEndDate().plusDays(1).atStartOfDay());
        List<UserScheduleViewBo> viewBos = userScheduleService.getScheduleView(userScheduleViewQuery);
        return ResponseEntity.ok(viewBos);
    }

    @ApiOperationSort(4)
    @PutMapping("schedule/check")
    @SysLog(operation = "点击完成当前提醒")
    @ApiOperation(value = "点击完成当前提醒")
    public ResponseEntity<Boolean> check(@RequestBody UserScheduleCheckParam checkParam) {
        UserScheduleCheckQuery checkQuery = MapperUtil.nf().map(checkParam, UserScheduleCheckQuery.class);
        Boolean checkResult = userScheduleService.check(checkQuery);
        return ResponseEntity.ok(checkResult);
    }

    @ApiOperationSort(5)
    @DeleteMapping("schedule")
    @SysLog(operation = "删除日程任务")
    @ApiOperation(value = "删除日程任务", notes = "指删除垃圾箱任务")
    public ResponseEntity<Boolean> delete(@RequestBody IdsParam idsParam) {
        Boolean checkResult = userScheduleService.deleteByIds(idsParam.getPids(), SecurityUtils.getUserId());
        return ResponseEntity.ok(checkResult);
    }

    @ApiOperationSort(6)
    @PostMapping("schedule/group")
    @SysLog(operation = "创建分组")
    @ApiOperation(value = "创建分组")
    public ResponseEntity<List<UserScheduleGroupBo>> addGroup(@RequestBody UserScheduleGroupAddParam userScheduleGroupAddParam) {
        UserScheduleGroupQuery scheduleGroupQuery = MapperUtil.nf().map(userScheduleGroupAddParam, UserScheduleGroupQuery.class);
        scheduleGroupQuery.setUserId(SecurityUtils.getUserId());
        List<UserScheduleGroupBo> userScheduleGroupBos = userScheduleGroupService.addGroup(scheduleGroupQuery);
        return ResponseEntity.ok(userScheduleGroupBos);
    }

    @ApiOperationSort(7)
    @PutMapping("schedule/group")
    @SysLog(operation = "更新分组")
    @ApiOperation(value = "更新分组")
    public ResponseEntity<List<UserScheduleGroupBo>> updateGroup(@RequestBody UserScheduleGroupUpdateParam userScheduleGroupUpdateParam) {
        AssertUtil.assertThrow("默认分组不可修改", UserScheduleGroup.DEFAULT_GROUP.contains(userScheduleGroupUpdateParam.getGroupId()));
        UserScheduleGroupQuery scheduleGroupQuery = MapperUtil.nf().map(userScheduleGroupUpdateParam, UserScheduleGroupQuery.class);
        scheduleGroupQuery.setUserId(SecurityUtils.getUserId());
        List<UserScheduleGroupBo> userScheduleGroupBos = userScheduleGroupService.updateGroup(scheduleGroupQuery);
        return ResponseEntity.ok(userScheduleGroupBos);
    }

    @ApiOperationSort(8)
    @GetMapping("schedule/group")
    @SysLog(operation = "查询分组")
    @ApiOperation(value = "查询分组")
    public ResponseEntity<List<UserScheduleGroupBo>> listGroup() {
        List<UserScheduleGroupBo> userScheduleGroupBos = userScheduleGroupService.listGroup(SecurityUtils.getUserId());
        return ResponseEntity.ok(userScheduleGroupBos);
    }

    @ApiOperationSort(9)
    @DeleteMapping("schedule/group/{groupId}")
    @SysLog(operation = "删除分组")
    @ApiOperation(value = "删除分组")
    public ResponseEntity<List<UserScheduleGroupBo>> deleteGroup(@PathVariable @NotBlank String groupId) {
        AssertUtil.assertThrow("默认分组不可删除", UserScheduleGroup.DEFAULT_GROUP.contains(groupId));
        UserScheduleGroupQuery scheduleGroupQuery = new UserScheduleGroupQuery()
                .setGroupId(groupId)
                .setUserId(SecurityUtils.getUserId());
        List<UserScheduleGroupBo> userScheduleGroupBos = userScheduleGroupService.deleteGroup(scheduleGroupQuery);
        return ResponseEntity.ok(userScheduleGroupBos);
    }

    @ApiOperationSort(10)
    @PostMapping("schedule/tag")
    @SysLog(operation = "创建标签")
    @ApiOperation(value = "创建标签")
    public ResponseEntity<List<UserScheduleTagBo>> addTag(@RequestBody UserScheduleTagAddParam userScheduleTagAddParam) {
        UserScheduleTagQuery scheduleTagQuery = MapperUtil.nf().map(userScheduleTagAddParam, UserScheduleTagQuery.class);
        scheduleTagQuery.setUserId(SecurityUtils.getUserId());
        List<UserScheduleTagBo> userScheduleTagBos = userScheduleTagService.addTag(scheduleTagQuery);
        return ResponseEntity.ok(userScheduleTagBos);
    }

    @ApiOperationSort(11)
    @PutMapping("schedule/tag")
    @SysLog(operation = "更新标签")
    @ApiOperation(value = "更新标签")
    public ResponseEntity<List<UserScheduleTagBo>> updateTag(@RequestBody UserScheduleTagUpdateParam userScheduleTagUpdateParam) {
        AssertUtil.assertThrow("默认标签不可修改", UserScheduleTag.DEFAULT_TAG.contains(userScheduleTagUpdateParam.getTagId()));
        UserScheduleTagQuery scheduleTagQuery = MapperUtil.nf().map(userScheduleTagUpdateParam, UserScheduleTagQuery.class);
        scheduleTagQuery.setUserId(SecurityUtils.getUserId());
        List<UserScheduleTagBo> userScheduleTagBos = userScheduleTagService.updateTag(scheduleTagQuery);
        return ResponseEntity.ok(userScheduleTagBos);
    }

    @ApiOperationSort(12)
    @GetMapping("schedule/tag")
    @SysLog(operation = "查询标签")
    @ApiOperation(value = "查询标签")
    public ResponseEntity<List<UserScheduleTagBo>> listTag() {
        List<UserScheduleTagBo> userScheduleTagBos = userScheduleTagService.listTag(SecurityUtils.getUserId());
        return ResponseEntity.ok(userScheduleTagBos);
    }

    @ApiOperationSort(13)
    @DeleteMapping("schedule/tag/{tagId}")
    @SysLog(operation = "删除标签")
    @ApiOperation(value = "删除标签")
    public ResponseEntity<List<UserScheduleTagBo>> deleteTag(@PathVariable @NotBlank String tagId) {
        AssertUtil.assertThrow("默认标签不可修改", UserScheduleTag.DEFAULT_TAG.contains(tagId));
        UserScheduleTagQuery userScheduleTagQuery = new UserScheduleTagQuery()
                .setTagId(tagId)
                .setUserId(SecurityUtils.getUserId());
        List<UserScheduleTagBo> userScheduleTagBos = userScheduleTagService.deleteTag(userScheduleTagQuery);
        return ResponseEntity.ok(userScheduleTagBos);
    }

    @ApiOperationSort(14)
    @PostMapping("schedule/meeting")
    @SysLog(operation = "创建会议")
    @ApiOperation(value = "创建会议")
    public ResponseEntity<Boolean> addMeeting(@RequestBody UserScheduleMeetingAddParam param) {
        UserScheduleMeetingAddQuery meetingAddQuery = MapperUtil.nf().map(param, UserScheduleMeetingAddQuery.class);
        meetingAddQuery.setUserId(SecurityUtils.getUserId());
        Boolean result = userScheduleMeetingService.addScheduleAndMeeting(meetingAddQuery);
        return ResponseEntity.ok(result);
    }

    @ApiOperationSort(15)
    @GetMapping("schedule/meeting")
    @SysLog(operation = "查询会议")
    @ApiOperation(value = "查询会议")
    @ApiImplicitParam(name = "meetingId", value = "会议id 为空时,查询列表")
    public ResponseEntity<List<MeetingBo>> getMeeting(@RequestParam(value = "meetingId", required = false) String meetingId) {
        String userId = SecurityUtils.getUserId();
        List<MeetingBo> meetingBos = userScheduleMeetingService.getMeeting(userId, meetingId);
        return ResponseEntity.ok(meetingBos);
    }

    @ApiOperationSort(16)
    @PutMapping("schedule/meeting")
    @SysLog(operation = "更改会议")
    @ApiOperation(value = "更改会议")
    public ResponseEntity<Boolean> updateMeeting(@RequestBody UserScheduleMeetingUpdateParam updateParam) {
        UserScheduleMeetingUpdateQuery updateQuery = MapperUtil.nf().map(updateParam, UserScheduleMeetingUpdateQuery.class);
        updateQuery.setUserId(SecurityUtils.getUserId());
        Boolean result = userScheduleMeetingService.updateMeeting(updateQuery);
        return ResponseEntity.ok(result);
    }

    @ApiOperationSort(17)
    @DeleteMapping("schedule/meeting/{meetingId}")
    @SysLog(operation = "删除/取消 会议")
    @ApiOperation(value = "删除/取消 会议")
    @ApiImplicitParam(name = "meetingId", value = "会议id", paramType = "path")
    public ResponseEntity<Boolean> deleteMeeting(@PathVariable @NotBlank String meetingId) {
        Boolean result = userScheduleMeetingService.deleteMeeting(meetingId);
        return ResponseEntity.ok(result);
    }

    @ApiOperationSort(17)
    @GetMapping("schedule/meeting/clash")
    @SysLog(operation = "会议冲突检查")
    @ApiOperation(value = "会议冲突检查")
    public ResponseEntity<List<String>> checkMeetingClash(UserMeetingClashParam clashParam) {
        AssertUtil.assertThrow("参数不合法", Objects.isNull(clashParam.getStartTime()) || Objects.isNull(clashParam.getEndTime()));
        AssertUtil.assertThrow("参数不合法", clashParam.getEndTime().isBefore(clashParam.getStartTime()));
        UserMeetingClashQuery meetingClashQuery = MapperUtil.nf().map(clashParam, UserMeetingClashQuery.class);
        // 检查自己
        if (CollectionUtils.isEmpty(clashParam.getUserIds())) {
            meetingClashQuery.setUserIds(Collections.singletonList(SecurityUtils.getUserId()));
        } else {
            meetingClashQuery.getUserIds().add(SecurityUtils.getUserId());
        }
        List<String> realOrUserNames = userScheduleService.checkMeetingClash(meetingClashQuery);
        return ResponseEntity.ok(realOrUserNames);
    }

}
